﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Xml;

namespace LaunchPad.Core
{
    public class TrackEvent : INotifyPropertyChanged
    {       
        public TrackEvent() : this(TimeSpan.Zero, TimeSpan.Zero, TimeSpan.Zero) { }

        public TrackEvent(TimeSpan time, TimeSpan leadIn, TimeSpan leadOut)
        {
            Time = time;
            LeadIn = leadIn;
            LeadOut = leadOut;
        }

        private TimeSpan _time;
        private TimeSpan _leadIn;
        private TimeSpan _leadOut;
        private TrackEventState _state;

        [XmlIgnore]
        public TimeSpan LeadIn
        {
            get { return _leadIn; }
            set
            {
                if (_leadIn != value)
                {
                    _leadIn = value;
                    OnPropertyChanged("LeadIn");
                    OnPropertyChanged("Start");
                }
            }
        }

        [XmlAttribute("LeadIn", DataType = "duration")]
        public string LeadInXml
        {
            get { return XmlConvert.ToString(LeadIn); }
            set { LeadIn = XmlConvert.ToTimeSpan(value); }
        }

        [XmlIgnore]
        public TimeSpan Time
        {
            get { return _time; }
            set
            {
                TimeSpan t = value;
                TimeSpan start = t - LeadIn;
                if (start < TimeSpan.Zero)
                    t = LeadIn;

                if (_time != t)
                {
                    _time = t;
                    OnPropertyChanged("Time");
                    OnPropertyChanged("Description");
                    OnPropertyChanged("Start");
                    OnPropertyChanged("Finish");
                }
            }
        }

        [XmlAttribute("Time", DataType = "duration")]
        public string TimeXml
        {
            get { return XmlConvert.ToString(Time); }
            set { Time = XmlConvert.ToTimeSpan(value); }
        }

        [XmlIgnore]
        public TimeSpan LeadOut
        {
            get { return _leadOut; }
            set
            {
                if (LeadOut != value)
                {
                    _leadOut = value;
                    OnPropertyChanged("LeadOut");
                    OnPropertyChanged("Finish");
                }
            }
        }

        [XmlAttribute("LeadOut", DataType = "duration")]
        public string LeadOutXml
        {
            get { return XmlConvert.ToString(LeadOut); }
            set { LeadOut = XmlConvert.ToTimeSpan(value); }
        }

        [XmlIgnore]
        public TimeSpan Start
        {
            get { return Time - LeadIn; }
            set
            {
                TimeSpan start = value;
                if (start < TimeSpan.Zero)
                    start = TimeSpan.Zero;

                if (Start != value)
                {
                    Time = start + LeadIn;
                }
            }
        }

        [XmlIgnore]
        public TimeSpan Finish
        {
            get { return Time + LeadOut; }
            set
            {
                if (Finish != value)
                {
                    Time = value - LeadOut;
                }
            }
        }

        [XmlIgnore]
        public TrackEventState State
        {
            get { return _state; }
            set
            {
                if (_state != value)
                {
                    _state = value;
                    OnPropertyChanged("State");
                }
            }
        }

        public void NudgeLeft()
        {
            Time -= TimeSpan.FromMilliseconds(100);
        }

        public void NudgeRight()
        {
            Time += TimeSpan.FromMilliseconds(100);
        }

        public bool Intersects(TimeSpan time)
        {
            return Start < time && Finish > time;
        }

        public bool Intersects(TimeSpan start, TimeSpan finish)
        {
            return Start <= finish && Finish >= start;
        }

        public bool Intersects(TrackEvent other)
        {
            return Intersects(other.Start, other.Finish);
        }

        public string Description
        {
            get
            {
                return Time.ToString("g");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}
